<?php
/***
* @version $Id: functions_user.php 336 2007-01-23 08:12:56Z flexiondotorg $
* @copyright (c) 2006 - 2007 Flexion.Org
*            (c) 2004        Graham Eames (phpbb@grahameames.co.uk)
*            (c) 2001 - 2006 phpBB Group
* @license   http://opensource.org/licenses/gpl-license.php GNU Public License
***/

if ( !defined('IN_R3BORN') )
{
	die('Hacking attempt');
}

// This code requires certain functions to be included, so we'll include the
// files just in case they are not already used on the calling page
// NB. This requires that the calling script has set the $root_path variable
// and also that the $db object has been initialized
include_once($root_path . 'includes/functions_validate.' . $phpEx);
include_once($root_path . 'includes/functions_message.' . $phpEx);
include_once($root_path . 'includes/functions_bbcode.' . $phpEx);

class user
{
	// These are the 3 critical values for any user
	var $username;
	var $user_password;
	var $user_email;

	var $user_id;

	// The remaining userdata fields are stored in an array
	var $user_fields;

	// This stores details of any usergroups that the user should be in
	var $groups;

	// The constructor for this class
	//
	// The password must be in MD5 format, but we'll handle escaping any special
	// characters in any field within the function
	function user($name, $password, $email)
	{
		global $config, $hooks;

		$this->username = $this->sql_escape($name);
		$this->user_password = $this->sql_escape($password);
		$this->user_email = $this->sql_escape($email);

		$this->user_id = '';

		// Now we need to set the remaining fields to some default values
		// If you wish to integrate with another MOD, you should add any initilization
		// it requires after this
		$this->user_fields['user_regdate'] = time();
		$this->user_fields['user_from'] = '';
		$this->user_fields['user_occ'] = '';
		$this->user_fields['user_interests'] = '';
		$this->user_fields['user_website'] = '';
		$this->user_fields['user_icq'] = '';
		$this->user_fields['user_aim'] = '';
		$this->user_fields['user_yim'] = '';
		$this->user_fields['user_msnm'] = '';
		$this->user_fields['user_sig'] = '';
		$this->user_fields['user_sig_bbcode_uid'] = ( $config['allow_bbcode'] ) ? make_bbcode_uid() : '';
		$this->user_fields['user_avatar'] = '';
		$this->user_fields['user_avatar_type'] = USER_AVATAR_NONE;
		$this->user_fields['user_viewemail'] = 1;
		$this->user_fields['user_attachsig'] = 1;
		$this->user_fields['user_allowsmile'] = $config['allow_smilies'];
		$this->user_fields['user_allowhtml'] = $config['allow_html'];
		$this->user_fields['user_allowbbcode'] = $config['allow_bbcode'];
		$this->user_fields['user_allow_viewonline'] = 1;
		$this->user_fields['user_timezone'] = $config['board_timezone'];
		$this->user_fields['user_dateformat'] = $config['default_dateformat'];
		$this->user_fields['user_lang'] = $config['default_lang'];
		$this->user_fields['user_style'] = $config['default_style'];
		$this->user_fields['user_level'] = USER;

		//$user_dst = 0;
		//$group_priority = 0;

	}

	// This function escapes any special characters in a string to allow for safe
	// use in the SQL query. It is used in the constructor and should be used on
	// any data passed to set_field()
	function sql_escape($data)
	{
		return str_replace("\'", "''", addslashes($data));
	}

	// This function is used to set any of the user fields if you do not want to
	// use the default values. Any field listed in the array in this function
	// will have special characters escaped
	function set_field($field_name, $data)
	{
		// It's not the most efficient, but we escape everything just to be safe
		$this->user_fields[$field_name] = $this->sql_escape($data);
	}

	// This function allows you to set a specific user_id for this user
	// You should only call this if you know that the user_id you are specifying
	// is not already in use.
	// This is provided mainly for convertor use and not for normal use
	function set_user_id($id)
	{
		$this->user_id = intval($id);
	}

	// This function returns the user_id of the user.
	// It is only really useful after the call to insert_user()
	function get_user_id()
	{
		return $this->user_id;
	}

	// This function is used to set any usergroups the user should be added to
	// upon registration.
	// It can be called as many times as required
	function add_to_group($group_id)
	{
		$this->groups[] = $group_id;
	}

	// This function validates the userdata to ensure that the user can be inserted
	// into the database. It checks for duplicate usernames, disallowed usernames,
	// invalid email addresses and disallowed email addresses
	//
	// Returns true if the user can be inserted, false otherwise
	function validate_user()
	{
		$name_check = validate_username(stripslashes(str_replace("''", "\'", $this->username)));
		if ($name_check['error'])
		{
			return false;
		}

		$email_check = validate_email(stripslashes(str_replace("''", "\'", $this->user_email)));
		if ($email_check['error'])
		{
			return false;
		}
		return true;
	}

	// This is the function which actually inserts the user into the database
	//
	// NB. This function does not validate the user allowing you to register names
	// and email addresses which might otherwise be disallowed, if you want to
	// validate the data you should call validate_user() first
	//
	// Returns true on success, false otherwise
	function insert_user($bypass_activation = true)
	{
		global $config, $db, $hooks, $lang, $root_path, $phpEx;
		global $password_confirm;
		global $unhtml_specialchars_match, $unhtml_specialchars_replace;

		$user_lang = $config['default_lang'];

		// Build the main SQL query
		// Get the user_id if one has not already been set
		if ($this->user_id == '')
		{
			$sql = "SELECT MAX(user_id) AS total
  						FROM " . USERS_TABLE;
			if ( !($result = $db->sql_query($sql)) )
			{
				message_die(GENERAL_ERROR, 'Could not obtain next user_id information', '', __LINE__, __FILE__, $sql);
			}
			if ( !($row = $db->sql_fetchrow($result)) )
			{
				message_die(GENERAL_ERROR, 'Could not obtain next user_id information', '', __LINE__, __FILE__, $sql);
			}
			$this->user_id = $row['total'] + 1;
		}

		$sql = "INSERT INTO " . USERS_TABLE . "	(user_id, username, user_regdate, user_password, user_email, user_icq, user_website, user_occ, user_from, user_interests, user_sig, user_sig_bbcode_uid, user_avatar, user_avatar_type, user_viewemail, user_aim, user_yim, user_msnm, user_attachsig, user_allowsmile, user_allowhtml, user_allowbbcode, user_allow_viewonline, user_timezone, user_dateformat, user_lang, user_style, user_level, user_active, user_actkey) ";
		$sql .= "VALUES (" . $this->user_id . ", '" . $this->username . "', '" . $this->user_fields['user_regdate'] . "', '" . $this->user_password . "', '" . $this->user_email . "', '" . $this->user_fields['user_icq'] . "', '" . $this->user_fields['user_website'] . "', '" . $this->user_fields['user_occ'] . "', '" . $this->user_fields['user_from'] . "', '" . $this->user_fields['user_interests'] . "', '" . $this->user_fields['user_sig'] . "', '" . $this->user_fields['user_sig_bbcode_uid'] . "', '" . $this->user_fields['user_avatar'] . "', '" . $this->user_fields['user_avatar_type'] . "', " . $this->user_fields['user_viewemail'] . ", '" . str_replace(' ', '+', $this->user_fields['user_aim']) . "', '" . $this->user_fields['user_yim'] . "', '" . $this->user_fields['user_msnm'] . "', " . $this->user_fields['user_attachsig'] . ", " . $this->user_fields['user_allowsmile'] . ", " . $this->user_fields['user_allowhtml'] . ", " . $this->user_fields['user_allowbbcode'] . ", " . $this->user_fields['user_allow_viewonline'] . ", " . $this->user_fields['user_timezone'] . ", '" . $this->user_fields['user_dateformat'] . "', '" . $this->user_fields['user_lang'] . "', " . $this->user_fields['user_style'] . ", " . $this->user_fields['user_level'] . ", ";

		$server_url = generate_website_url() . append_sid('register.' . $phpEx);;

		if ( ($config['require_activation'] == USER_ACTIVATION_SELF || $config['require_activation'] == USER_ACTIVATION_ADMIN ) && !$bypass_activation )
		{
			$user_actkey = gen_rand_string(true);
			$key_len = 54 - (strlen($server_url));
			$key_len = ( $key_len > 6 ) ? $key_len : 6;
			$user_actkey = substr($user_actkey, 0, $key_len);
			$sql .= "0, '" . str_replace("\'", "''", $user_actkey) . "')";
		}
		else
		{
			$sql .= "1, '')";
		}

		// Insert the user
		if ( !($result = $db->sql_query($sql, BEGIN_TRANSACTION)) )
		{
			$error = true;
		}

		//Set the user id accordingly.
		//$this->user_id = ($this->user_id) ? $this->user_id : $db->sql_nextid();

		// Insert the personal group
		$sql = "INSERT INTO " . GROUPS_TABLE . " (group_name, group_description, group_single_user, group_moderator)
			VALUES ('', 'Personal User', 1, 0)";
		if ( !($result = $db->sql_query($sql)) )
		{
			$error = true;
		}

		$group_id = $db->sql_nextid();

		// Insert the user_group entry
		$sql = "INSERT INTO " . USER_GROUP_TABLE . " (user_id, group_id, user_pending)
			VALUES (" . $this->user_id . ", $group_id, 0)";
		if( !($result = $db->sql_query($sql, END_TRANSACTION)) )
		{
			$error = true;
		}

		// Add the user to any applicable groups
		for ($i=0; $i<count($this->groups); $i++)
		{
			$sql = "INSERT INTO " . USER_GROUP_TABLE . " (user_id, group_id, user_pending)
				VALUES (" . $this->user_id . ", " . $this->groups[$i] . ", 0)";
			if( !($result = $db->sql_query($sql)) )
			{
				$error = true;
			}
		}

		$hooks->execute('insert_user', $this->get_user_id());

		//If the activation is not being bypassed then send out the appropriate e-mails.
		if (!$bypass_activation)
		{
			if ( $config['require_activation'] == USER_ACTIVATION_SELF )
			{
				$message = $lang['Account_inactive'];
				$email_template = 'user_welcome_inactive';
			}
			else if ( $config['require_activation'] == USER_ACTIVATION_ADMIN )
			{
				$message = $lang['Account_inactive_admin'];
				$email_template = 'admin_welcome_inactive';
			}
			else
			{
				$message = $lang['Account_added'];
				$email_template = 'user_welcome';
			}

			include($root_path . 'includes/class_emailer.'.$phpEx);
			$emailer = new emailer($config['smtp_delivery']);

			$emailer->from($config['board_email']);
			$emailer->replyto($config['board_email']);

			$emailer->use_template($email_template, stripslashes($user_lang));
			$emailer->email_address($this->user_email);
			$emailer->set_subject(sprintf($lang['Welcome_subject'], $config['sitename']));

			$emailer->assign_vars(array(
				'SITENAME' => $config['sitename'],
				'WELCOME_MSG' => sprintf($lang['Welcome_subject'], $config['sitename']),
				'USERNAME' => preg_replace($unhtml_specialchars_match, $unhtml_specialchars_replace, substr(str_replace("\'", "'", $this->username), 0, 25)),
				'PASSWORD' => $password_confirm,
				'EMAIL_SIG' => str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']),
				'U_ACTIVATE' => $server_url . '?mode=activate&' . POST_USERS_URL . '=' . $this->user_id . '&act_key=' . $user_actkey)
			);

			$emailer->send();
			$emailer->reset();

			if ( $config['require_activation'] == USER_ACTIVATION_ADMIN )
			{
				$sql = "SELECT user_email, user_lang
						FROM " . USERS_TABLE . "
						WHERE user_level = " . ADMIN;

				if ( !($result = $db->sql_query($sql)) )
				{
					message_die(GENERAL_ERROR, 'Could not select Administrators', '', __LINE__, __FILE__, $sql);
				}

				while ($row = $db->sql_fetchrow($result))
				{
					$emailer->from($config['board_email']);
					$emailer->replyto($config['board_email']);

					$emailer->email_address(trim($row['user_email']));
					$emailer->use_template("admin_activate", $row['user_lang']);
					$emailer->set_subject($lang['New_account_subject']);

					$emailer->assign_vars(array(
						'USERNAME' => preg_replace($unhtml_specialchars_match, $unhtml_specialchars_replace, substr(str_replace("\'", "'", $this->username), 0, 25)),
						'EMAIL_SIG' => str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']),
						'U_ACTIVATE' => $server_url . '?mode=activate&' . POST_USERS_URL . '=' . $this->user_id . '&act_key=' . $user_actkey)
					);
					$emailer->send();
					$emailer->reset();
				}
				$db->sql_freeresult($result);
			}
			$message = $message . '<br /><br />' . sprintf($lang['Click_return_index'],  '<a href="' . append_sid("index.$phpEx") . '">', '</a>');
			message_die(GENERAL_MESSAGE, $message);
		}

		return ($error == true) ? false : true;
	}
}

// Now we have a few wrapper functions for those who don't need the full power
// of the class and just want to call a simple function
function insert_user($username, $user_password, $user_email, $bypass_activation = true, $group_id = '')
{

	loadHooks(getHooks('user'));

	$user = new user($username, $user_password, $user_email);

	if ($group_id != '')
	{
		$user->add_to_group($group_id);
	}

	$result = $user->validate_user();
	if ($result)
	{
		$result = $user->insert_user($bypass_activation);
	}

	return $result;
}

function delete_user($user_id)
{
	global $db, $this_userdata, $hooks;

	//loadHooks(getHooks('user'));

	$sql = "SELECT g.group_id
				FROM " . USER_GROUP_TABLE . " ug, " . GROUPS_TABLE . " g
				WHERE ug.user_id = $user_id
					AND g.group_id = ug.group_id
					AND g.group_single_user = 1";
	if( !($result = $db->sql_query($sql)) )
	{
		message_die(GENERAL_ERROR, 'Could not obtain group information for this user', '', __LINE__, __FILE__, $sql);
	}

	$row = $db->sql_fetchrow($result);

	$sql = "SELECT group_id
			FROM " . GROUPS_TABLE . "
			WHERE group_moderator = $user_id";
	if( !($result = $db->sql_query($sql)) )
	{
		message_die(GENERAL_ERROR, 'Could not select groups where user was moderator', '', __LINE__, __FILE__, $sql);
	}

	while ( $row_group = $db->sql_fetchrow($result) )
	{
		$group_moderator[] = $row_group['group_id'];
	}

	if ( count($group_moderator) )
	{
		$update_moderator_id = implode(', ', $group_moderator);

		$sql = "UPDATE " . GROUPS_TABLE . "
				SET group_moderator = " . $this_userdata['user_id'] . "
				WHERE group_moderator IN ($update_moderator_id)";
		if( !$db->sql_query($sql) )
		{
			message_die(GENERAL_ERROR, 'Could not update group moderators', '', __LINE__, __FILE__, $sql);
		}
	}

	$sql = "DELETE FROM " . USERS_TABLE . "
			WHERE user_id = $user_id";
	if( !$db->sql_query($sql) )
	{
		message_die(GENERAL_ERROR, 'Could not delete user', '', __LINE__, __FILE__, $sql);
	}

	$sql = "DELETE FROM " . USER_GROUP_TABLE . "
			WHERE user_id = $user_id";
	if( !$db->sql_query($sql) )
	{
		message_die(GENERAL_ERROR, 'Could not delete user from user_group table', '', __LINE__, __FILE__, $sql);
	}

	$sql = "DELETE FROM " . GROUPS_TABLE . "
			WHERE group_id = " . $row['group_id'];
	if( !$db->sql_query($sql) )
	{
		message_die(GENERAL_ERROR, 'Could not delete group for this user', '', __LINE__, __FILE__, $sql);
	}

	$sql = "DELETE FROM " . USER_GROUP_AUTH_ACCESS_TABLE . "
			WHERE group_id = " . $row['group_id'];
	if( !$db->sql_query($sql) )
	{
		message_die(GENERAL_ERROR, 'Could not delete group for this user', '', __LINE__, __FILE__, $sql);
	}

	$sql = "DELETE FROM " . JR_ADMIN_TABLE . "
			WHERE user_id = $user_id";
	if( !$db->sql_query($sql) )
	{
		message_die(GENERAL_ERROR, 'Could not delete user from Jnr. Admins', '', __LINE__, __FILE__, $sql);
	}

	$sql = "DELETE FROM " . ADMIN_NAV_TABLE . "
			WHERE user_id = $user_id";
	if( !$db->sql_query($sql) )
	{
		message_die(GENERAL_ERROR, 'Could not delete user from Admin modules', '', __LINE__, __FILE__, $sql);
	}

	$sql = "DELETE FROM " . BANLIST_TABLE . "
			WHERE ban_userid = $user_id";
	if ( !$db->sql_query($sql) )
	{
		message_die(GENERAL_ERROR, 'Could not delete user from banlist table', '', __LINE__, __FILE__, $sql);
	}

	$sql = "DELETE FROM " . SESSIONS_TABLE . "
			WHERE session_user_id = $user_id";
	if ( !$db->sql_query($sql) )
	{
		message_die(GENERAL_ERROR, 'Could not delete sessions for this user', '', __LINE__, __FILE__, $sql);
	}

	$sql = "DELETE FROM " . SESSIONS_KEYS_TABLE . "
			WHERE user_id = $user_id";
	if ( !$db->sql_query($sql) )
	{
		message_die(GENERAL_ERROR, 'Could not delete auto-login keys for this user', '', __LINE__, __FILE__, $sql);
	}

	$hooks->execute('delete_user', $user_id, $row['group_id']);

	return;
}
?>